package juc.work;

import java.util.ArrayDeque;

/**
 * 生产者消费者模型 实现2
 * 更简单适合面试
 */
class ProductStorage {
    private int capacity;
    private ArrayDeque<Object> storage;

    public ProductStorage(int capacity) {
        this.capacity = capacity;
        storage = new ArrayDeque<>(capacity);
    }

    // put
    public synchronized void put() {
        while (storage.size() == capacity) {
            try {
                wait();
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }

        storage.add(new Object());
        System.out.println("缓存区有 " + storage.size() + " 个产品");
        notifyAll();
    }

    // take
    public synchronized void take() {
        while(storage.size() == 0) {
            try {
                wait();
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
        storage.remove();
        System.out.println("从缓存区消费，缓存区还剩下" + storage.size() + " 个产品");
        notifyAll();
    }

}

class SimpleConsumer implements Runnable {
    private ProductStorage storage;

    public SimpleConsumer(ProductStorage storage) {
        this.storage = storage;
    }

    @Override
    public void run() {
        while (true) {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            storage.take();
        }
    }
}

class SimpleProducer implements Runnable {
    private ProductStorage storage;

    public SimpleProducer(ProductStorage storage) {
        this.storage = storage;
    }

    @Override
    public void run() {
        while (true) {
            storage.put();
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }
}

public class ProducerConsumerModel {
    public static void main(String[] args) {
        ProductStorage productStorage = new ProductStorage(10);
        Thread consumer1 = new Thread(new SimpleConsumer(productStorage));
        Thread consumer2 = new Thread(new SimpleConsumer(productStorage));
        Thread producer1 = new Thread(new SimpleProducer(productStorage));
        Thread producer2 = new Thread(new SimpleProducer(productStorage));
        producer1.start();
        producer2.start();
        consumer1.start();
        consumer2.start();
    }
}
